﻿namespace Pap.Web.Modules.Membership.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using Microsoft.Practices.ServiceLocation;
    using Pap.Data;
    using Pap.Web.Utils;

    /// <summary>
    /// The class for UserDetailsViewModel
    /// </summary>
    public class UserDetailsViewModel : IViewModel
    {
        /// <summary>
        /// The local membership repository instance
        /// </summary>
        private IMembershipRepository _MembershipRepository;

        /// <summary>
        /// 
        /// </summary>
        private IAdministrationRepository _AdministrationRepository;

        /// <summary>
        /// Initializes a new instance of the <see cref="UserDetailsViewModel"/> class.
        /// </summary>
        /// <param name="membershipRepository">The membership repository.</param>
        /// <param name="AdministrationRepository">The administration repository.</param>
        public UserDetailsViewModel(IMembershipRepository membershipRepository, IAdministrationRepository AdministrationRepository)
        {
            this._MembershipRepository = membershipRepository;
            this._AdministrationRepository = AdministrationRepository;
        }

        /// <summary>
        /// checks whether the user name exists.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public bool DoesUserNameExist(string userName, Guid? userId)
        {
            Expression<Func<IUser, bool>> expression = user => user.Username.ToLower() == userName.ToLower();
            if (!userId.HasValue)
            {
                return (_MembershipRepository.FindUsers(expression).Count() > 0);
            }
            else
            {
                IEnumerable<IUser> result = _MembershipRepository.FindUsers(expression);
                if (result.Count() == 1)
                {
                    if (result.First().UserID == userId.Value)
                        return false;
                    else return true;
                }
                else return false;
            }
        }

        /// <summary>
        /// checks whether the user email exists.
        /// </summary>
        /// <param name="email">The email.</param>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public bool DoesUserEmailExist(string email, Guid? userId)
        {
            Expression<Func<IUser, bool>> expression = user => user.Email.ToLower() == email.ToLower();
            if (!userId.HasValue)
            {
                return (_MembershipRepository.FindUsers(expression).Count() > 0);
            }
            else
            {
                IEnumerable<IUser> result = _MembershipRepository.FindUsers(expression);
                if (result.Count() == 1)
                {
                    if (result.First().UserID == userId.Value)
                        return false;
                    else return true;
                }
                else return false;
            }
        }

        /// <summary>
        /// Creates the user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <param name="displayName">The display name.</param>
        /// <param name="birthDate">The birth date.</param>
        /// <param name="email">The email.</param>
        /// <param name="jobTitle">The job title.</param>
        /// <param name="roles">The roles.</param>
        /// <param name="CommitteesIDs">The committees I ds.</param>
        /// <param name="projectID">The project ID.</param>
        public void CreateUser(string userName, string password, string displayName, DateTime birthDate, string email, string jobTitle, List<Guid> roles, List<Guid> CommitteesIDs, List<Guid> ProjectIDs)
        {
            using (Pap.Data.Abstraction.Utils.IUnitOfWork transaction = ServiceLocator.Current.GetInstance<Pap.Data.Abstraction.Utils.IUnitOfWork>())
            {
                IUser createdUser = ServiceLocator.Current.GetInstance<IUser>();
                createdUser.UserID = Guid.NewGuid();
                createdUser.Username = userName;
                createdUser.Password = password;
                createdUser.DisplayName = displayName;
                createdUser.Birthdate = birthDate;
                createdUser.Email = email;
                createdUser.JobTitle = jobTitle;

                IEnumerable<IRole> roleLst = _MembershipRepository.FindRoles(r => roles.Contains(r.RoleID));
                createdUser.ChangeRoles(roleLst);

                IEnumerable<ICommittee> commiteeLst = _AdministrationRepository.FindCommittees(c => CommitteesIDs.Contains(c.CommitteeID));
                createdUser.ChangeCommittees(commiteeLst);

                IEnumerable<IProject> projectLst = _AdministrationRepository.FindProjects(c => ProjectIDs.Contains(c.ProjectID));
                createdUser.ChangeProjects(projectLst);

                this._MembershipRepository.CreateUser(createdUser);
                transaction.Commit();
            }
        }

        /// <summary>
        /// Updates the user.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <param name="displayName">The display name.</param>
        /// <param name="birthDate">The birth date.</param>
        /// <param name="email">The email.</param>
        /// <param name="jobTitle">The job title.</param>
        /// <param name="roles">The roles.</param>
        /// <param name="CommitteesIDs">The committees I ds.</param>
        /// <param name="ProjectID">The project IDs.</param>
        public void UpdateUser(Guid userId, string userName, string password, string displayName, DateTime birthDate, string email, string jobTitle, List<Guid> roles, List<Guid> CommitteesIDs, List<Guid> ProjectIDs)
        {
            using (Pap.Data.Abstraction.Utils.IUnitOfWork transaction = ServiceLocator.Current.GetInstance<Pap.Data.Abstraction.Utils.IUnitOfWork>())
            {
                IUser user = this._MembershipRepository.GetUserByID(userId);
                user.Username = userName;
                user.Password = password;
                user.DisplayName = displayName;
                user.Birthdate = birthDate;
                user.Email = email;
                user.JobTitle = jobTitle;
                

                IEnumerable<IRole> roleLst = _MembershipRepository.FindRoles(r => roles.Contains(r.RoleID));
                user.ChangeRoles(roleLst);
                IEnumerable<ICommittee> commiteeLst = _AdministrationRepository.FindCommittees(c => CommitteesIDs.Contains(c.CommitteeID));
                user.ChangeCommittees(commiteeLst);

                IEnumerable<IProject> projectLst = _AdministrationRepository.FindProjects(c => ProjectIDs.Contains(c.ProjectID));
                user.ChangeProjects(projectLst);

                transaction.Commit();
            }
        }

        /// <summary>
        /// Gets the user by ID.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public IUser GetUserByID(Guid userId)
        {
            return this._MembershipRepository.GetUserByID(userId);
        }

        /// <summary>
        /// Gets all roles.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<IRole> GetAllRoles()
        {
            return this._MembershipRepository.FindRoles(role => true);
        }
        /// <summary>
        /// Gets all committees.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ICommittee> GetAllCommittees()
        {
            return this._AdministrationRepository.FindCommittees(committee => true);
        }
        /// <summary>
        /// Gets all projects.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<IProject> GetAllProjects()
        {
            return this._AdministrationRepository.FindProjects(project => true);
        }
    }
}
